/* 
 *	adc≈
 *	External object for Jammoma Multicore
 *	Copyright © 2009 by Timothy Place
 * 
 *	License: This code is licensed under the terms of the GNU LGPL
 *	http://www.gnu.org/licenses/lgpl.html 
 */

#include "maxMulticore.h"


// Data Structure for this object
struct MCoreADC {
    Object			obj;
	MCoreObjectPtr	mcore;
	TTPtr			mcoreOutlet;
	TTUInt32		numChannels;
	TTUInt16		vectorSize;
};
typedef MCoreADC* MCoreAdcPtr;


// Prototypes for methods
MCoreAdcPtr	mcoreAdcNew(SymbolPtr msg, AtomCount argc, AtomPtr argv);
void		mcoreAdcFree(MCoreAdcPtr x);
void		mcoreAdcAssist(MCoreAdcPtr x, void* b, long msg, long arg, char* dst);
TTErr		mcoreAdcReset(MCoreAdcPtr x, long vectorSize);
//TTErr		mcoreAdcObject(MCoreAdcPtr x, MCoreObjectPtr audioSourceObject, long sourceOutletNumber);
TTErr		mcoreAdcSetup(MCoreAdcPtr x);
TTErr		mcoreAdcStart(MCoreAdcPtr x);
TTErr		mcoreAdcStop(MCoreAdcPtr x);
// Prototypes for attribute accessors
MaxErr		mcoreAdcSetSampleRate(MCoreAdcPtr x, void* attr, AtomCount argc, AtomPtr argv);
MaxErr		mcoreAdcGetSampleRate(MCoreAdcPtr x, void* attr, AtomCount* argc, AtomPtr* argv);
MaxErr		mcoreAdcSetVectorSize(MCoreAdcPtr x, void* attr, AtomCount argc, AtomPtr argv);
MaxErr		mcoreAdcGetVectorSize(MCoreAdcPtr x, void* attr, AtomCount* argc, AtomPtr* argv);
//t_int*		mcoreAdcPerform(t_int* w);
//void		mcoreAdcDsp(MCoreAdcPtr x, t_signal** sp, short* count);


// Globals
static ClassPtr sMCoreAdcClass;


/************************************************************************************/
// Main() Function

int main(void)
{
	t_class *c;
	
	MCoreInit();	
	common_symbols_init();
	
	c = class_new("adc≈", (method)mcoreAdcNew, (method)mcoreAdcFree, sizeof(MCoreADC), (method)0L, A_GIMME, 0);
	
	class_addmethod(c, (method)mcoreAdcStart,			"start",			0);
	class_addmethod(c, (method)mcoreAdcStop,			"stop",				0);
	//class_addmethod(c, (method)mcoreAdcNotify,		"notify",			A_CANT, 0);
	class_addmethod(c, (method)mcoreAdcReset,			"multicore.reset",	A_CANT, 0);
	class_addmethod(c, (method)mcoreAdcSetup,			"multicore.setup",		A_CANT, 0);
//	class_addmethod(c, (method)mcoreAdcObject,			"multicore.signal",	A_OBJ, A_LONG, 0);
// 	class_addmethod(c, (method)mcoreAdcDsp,				"dsp",				A_CANT, 0);		
	class_addmethod(c, (method)mcoreAdcAssist,			"assist",			A_CANT, 0); 
    class_addmethod(c, (method)object_obex_dumpout,		"dumpout",			A_CANT, 0);  
	
	CLASS_ATTR_LONG(c,		"sampleRate",	0,		MCoreADC,	obj);
	CLASS_ATTR_ACCESSORS(c,	"sampleRate",	mcoreAdcGetSampleRate,	mcoreAdcSetSampleRate);
	
	CLASS_ATTR_LONG(c,		"vectorSize",	0,		MCoreADC,	obj);
	CLASS_ATTR_ACCESSORS(c,	"vectorSize",	mcoreAdcGetVectorSize,	mcoreAdcSetVectorSize);
	
	class_dspinit(c);
	class_register(_sym_box, c);
	sMCoreAdcClass = c;
	return 0;
}


/************************************************************************************/
// Life Cycle

MCoreAdcPtr mcoreAdcNew(SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
    MCoreAdcPtr	x = MCoreAdcPtr(object_alloc(sMCoreAdcClass));
	TTValue		v;
	TTErr		err;
	
    if(x){
		v.setSize(2);
		v.set(0, TT("multicore.input"));
		v.set(1, 2);
		err = TTObjectInstantiate(TT("multicore.object"), (TTObjectPtr*)&x->mcore, v);

		v = TTPtr(x->mcore);
		x->mcore->audioObject->sendMessage(TT("setOwner"), v);

		attr_args_process(x,argc,argv);
		object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x,NULL));
		x->mcoreOutlet = outlet_new((t_pxobject *)x, "multicore.signal");
	}
	return x;
}


void mcoreAdcFree(MCoreAdcPtr x)
{
	TTObjectRelease((TTObjectPtr*)&x->mcore);
}


/************************************************************************************/
// Methods bound to input/inlets

// Method for Assistance Messages
void mcoreAdcAssist(MCoreAdcPtr x, void* b, long msg, long arg, char* dst)
{
	if(msg==1)			// Inlets
		strcpy(dst, "multichannel audio connection and control messages");		
	else if(msg==2)		// Outlets
		strcpy(dst, "dumpout");
}


TTErr mcoreAdcReset(MCoreAdcPtr x, long vectorSize)
{
	return x->mcore->resetSources(vectorSize);
}


TTErr mcoreAdcSetup(MCoreAdcPtr x)
{
	Atom a[2];
	
	atom_setobj(a+0, ObjectPtr(x->mcore));
	atom_setlong(a+1, 0);
	outlet_anything(x->mcoreOutlet, gensym("multicore.signal"), 2, a);
	return kTTErrNone;
}

//TTErr mcoreAdcObject(MCoreAdcPtr x, MCoreObjectPtr audioSourceObject, long sourceOutletNumber)
//{
//	return x->mcore->addSource(audioSourceObject, sourceOutletNumber);
//}


TTErr mcoreAdcStart(MCoreAdcPtr x)
{
	return x->mcore->audioObject->sendMessage(TT("start"));
}


TTErr mcoreAdcStop(MCoreAdcPtr x)
{	
	return x->mcore->audioObject->sendMessage(TT("stop"));
}


MaxErr mcoreAdcSetSampleRate(MCoreAdcPtr x, void* attr, AtomCount argc, AtomPtr argv)
{
	if(argc){
		long sr = atom_getlong(argv);
		x->mcore->audioObject->setAttributeValue(TT("sampleRate"), sr);
	}
	return MAX_ERR_NONE;
}


MaxErr mcoreAdcGetSampleRate(MCoreAdcPtr x, void* attr, AtomCount* argc, AtomPtr* argv)
{
	long sr;
	
	x->mcore->audioObject->getAttributeValue(TT("sampleRate"), sr);
	
	*argc = 1;
	if (!(*argv)) // otherwise use memory passed in
		*argv = (t_atom *)sysmem_newptr(sizeof(t_atom));
	atom_setlong(*argv, sr);
	return MAX_ERR_NONE;
}


MaxErr mcoreAdcSetVectorSize(MCoreAdcPtr x, void* attr, AtomCount argc, AtomPtr argv)
{
	if(argc){
		long vs = atom_getlong(argv);
		x->mcore->audioObject->setAttributeValue(TT("vectorSize"), vs);
	}
	return MAX_ERR_NONE;
}


MaxErr mcoreAdcGetVectorSize(MCoreAdcPtr x, void* attr, AtomCount* argc, AtomPtr* argv)
{
	long vs;
	
	x->mcore->audioObject->getAttributeValue(TT("vectorSize"), vs);
	
	*argc = 1;
	if (!(*argv)) // otherwise use memory passed in
		*argv = (t_atom *)sysmem_newptr(sizeof(t_atom));
	atom_setlong(*argv, vs);
	return MAX_ERR_NONE;
}


